package seatiger.tomcat.catalina.connector;


import seatiger.tomcat.catalina.*;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;

/**
 * 实现了HttpServletRequest，并对coyote.Request 进行包装
 */
public class NewRequest implements HttpServletRequest {

    /**
     * 关联的coyote Request
     */
    protected seatiger.tomcat.coyote.Request coyoteRequest;

    /**
     * 关联的连接对象
     */
    protected CoyoteConnector connector;

    /**
     * 关联的Context对象
     */
    protected Context context;

    protected Wrapper wrapper;

    protected InputBuffer inputBuffer = new InputBuffer();

    protected CoyoteInputStream inputStream =  new CoyoteInputStream(inputBuffer);

    /**
     * 返回这个类的门面
     */
    protected HttpRequestFacade facade = null;

    /**
     * 当前活跃的session
     */
    protected Session session = null;

    /**
     * 请求中携带的sessionId
     */
    protected String requestedSessionId = null;

    /**
     * 标记session 是否是url 重写的
     */
    protected boolean requestedSessionURL = false;

    protected NewResponse response = null;

    /**
     * 门面模式，servlet用户拿到的就是这个
     * @return
     */
    public HttpServletRequest getRequest() {
        if (facade == null) {
            facade = new HttpRequestFacade(this);
        }
        return facade;
    }

    public void setRequestedSessionURL(boolean flag) {
        this.requestedSessionURL = flag;
    }

    public boolean isRequestedSessionURL() {
        return requestedSessionURL;
    }

    public void setRequestedSessionId(String requestedSessionId) {
        this.requestedSessionId = requestedSessionId;
    }

    public void setCoyoteRequest(seatiger.tomcat.coyote.Request coyoteRequest) {
        this.coyoteRequest = coyoteRequest;
        this.inputBuffer.setCoyoteRequest(coyoteRequest);
    }

    public void setResponse(NewResponse response) {
        this.response = response;
    }

    public seatiger.tomcat.coyote.Request getCoyoteRequest() {
        return coyoteRequest;
    }

    public CoyoteConnector getConnector() {
        return connector;
    }

    public void setConnector(CoyoteConnector connector) {
        this.connector = connector;
    }

    public void setContext(Context context) {
        this.context = context;
    }

    public Context getContext() {
        return context;
    }

    public Host getHost() {
        if (getContext() == null) {
            return null;
        }
        return (Host) getContext().getParent();
    }

    public Wrapper getWrapper() {
        return wrapper;
    }

    public void setWrapper(Wrapper wrapper) {
        this.wrapper = wrapper;
    }

    /**
     * 返回CoyoteInputStream ，内部使用InputBuffer读取数据
     * @return
     * @throws IOException
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (inputStream == null) {
            inputStream = new CoyoteInputStream(inputBuffer);
        }
        return inputStream;
    }

    @Override
    public String getAuthType() {
        return null;
    }

    @Override
    public Cookie[] getCookies() {
        return new Cookie[0];
    }

    @Override
    public long getDateHeader(String name) {
        return 0;
    }

    @Override
    public String getHeader(String name) {
        return coyoteRequest.getMimeHeaders().getHeader(name);
    }

    @Override
    public Enumeration getHeaders(String name) {
        return null;
    }

    @Override
    public Enumeration getHeaderNames() {
        return null;
    }

    @Override
    public int getIntHeader(String name) {
        return 0;
    }

    @Override
    public String getMethod() {
        return coyoteRequest.method().toString();
    }

    @Override
    public String getPathInfo() {
        return null;
    }

    @Override
    public String getPathTranslated() {
        return null;
    }

    @Override
    public String getContextPath() {
        return null;
    }

    @Override
    public String getQueryString() {
        String queryString = coyoteRequest.queryString().toString();
        if (queryString == null || "".equals(queryString)){
            return null;
        }
        return queryString;
    }

    @Override
    public String getRemoteUser() {
        return null;
    }

    @Override
    public boolean isUserInRole(String role) {
        return false;
    }

    @Override
    public Principal getUserPrincipal() {
        return null;
    }

    @Override
    public String getRequestedSessionId() {
        return requestedSessionId;
    }

    @Override
    public String getRequestURI() {
        return coyoteRequest.requestURI().toString();
    }

    @Override
    public StringBuffer getRequestURL() {
        return null;
    }

    @Override
    public String getServletPath() {
        return null;
    }

    @Override
    public HttpSession getSession(boolean create) {
        Session session = doGetSession(create);
        if (session != null){
            return session.getSession();
        }else {
            return null;
        }
    }

    @Override
    public HttpSession getSession() {
        Session session = doGetSession(true);
        if (session != null){
            return session.getSession();
        }else {
            return null;
        }
    }

    protected Session doGetSession(boolean create) {
        Manager manager;
        if (context == null || (manager = context.getManager()) == null){
            return null;
        }

        if (session != null && !session.isValid()){
            session = null;
        }
        if (session != null){
            return session;
        }
        if (requestedSessionId != null){
            try {
                session = manager.findSession(requestedSessionId);
                if (session != null && !session.isValid()){
                    session = null;
                }
                if (session != null) {
                    session.access();
                    return session;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //创建新的session
        if (create){
            this.session = manager.createSession();
        }
        //创建一个Cookie,并添加到报文头中
        if (session != null && getContext() != null){
            Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME, session.getId());
            String path = getContext().getPath();
            if (path != null && !"".equals(path)){
                cookie.setPath(path);
            }else {
                cookie.setPath("/");
            }
            //将Cookie添加到报文头中
            response.addCookieInternal(cookie);
        }
        if (session != null){
            session.access();
        }
        return session;
    }

    @Override
    public boolean isRequestedSessionIdValid() {
        return false;
    }

    @Override
    public boolean isRequestedSessionIdFromCookie() {
        return false;
    }

    @Override
    public boolean isRequestedSessionIdFromURL() {
        return false;
    }

    @Override
    public boolean isRequestedSessionIdFromUrl() {
        return false;
    }

    @Override
    public Object getAttribute(String name) {
        return null;
    }

    @Override
    public Enumeration getAttributeNames() {
        return null;
    }

    @Override
    public String getCharacterEncoding() {
        return null;
    }

    @Override
    public void setCharacterEncoding(String s) throws UnsupportedEncodingException {

    }

    @Override
    public int getContentLength() {
        return coyoteRequest.getContentLength();
    }

    @Override
    public String getContentType() {
        return null;
    }



    @Override
    public String getParameter(String name) {
        return null;
    }

    @Override
    public Enumeration getParameterNames() {
        return null;
    }

    @Override
    public String[] getParameterValues(String name) {
        return new String[0];
    }

    @Override
    public Map getParameterMap() {
        return null;
    }

    @Override
    public String getProtocol() {
        return null;
    }

    @Override
    public String getScheme() {
        return null;
    }

    @Override
    public String getServerName() {
        return null;
    }

    @Override
    public int getServerPort() {
        return 0;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return null;
    }

    @Override
    public String getRemoteAddr() {
        return null;
    }

    @Override
    public String getRemoteHost() {
        return null;
    }

    @Override
    public void setAttribute(String name, Object o) {

    }

    @Override
    public void removeAttribute(String name) {

    }

    @Override
    public Locale getLocale() {
        return null;
    }

    @Override
    public Enumeration getLocales() {
        return null;
    }

    @Override
    public boolean isSecure() {
        return false;
    }

    @Override
    public RequestDispatcher getRequestDispatcher(String path) {
        return null;
    }

    @Override
    public String getRealPath(String path) {
        return null;
    }
}
